#ifndef __TASK_HPP__
#define __TASK_HPP__
#include "Poco/Poco.h"
#include "Poco/Process.h"
#include "imagefusion.grpc.pb.h"
#include "imagefusion.pb.h"
#include <Poco/Util/Application.h>
#include <fstream>
#include <grpc++/server.h>
#include <grpc++/server_builder.h>
#include <grpc++/server_context.h>
#include <grpcpp/grpcpp.h>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
using com::hh::imagefusion::CameraInfo;
using com::hh::imagefusion::CameraInfoResponse;
using com::hh::imagefusion::FusionService;
using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;

using namespace Poco;
using Poco::Process;
using Poco::ProcessHandle;

const std::string PIDFILE = "/var/run/imagefusion.pid";

void writePid2File( pid_t pid ) {
    std::ofstream out( PIDFILE, std::ios::ate );
    out << pid;
}

pid_t getLastPid() {
    if ( access( PIDFILE.c_str(), F_OK ) != 0 )
        return -1;
    std::ifstream in( PIDFILE );
    std::string line;
    getline( in, line );
    return std::stoi( line );
}

class FusionServiceImpl final : public FusionService::Service {
    Status pushCameraInfo( ServerContext* context, const CameraInfo* request, CameraInfoResponse* reply ) {
        Poco::Util::Application::instance().logger().information( "recieve camera fusion request..." );
        std::cout << "recieve camera fusion request..." << std::endl;
        std::stringstream ss;
        ss << "rtsp://" << request->username() << ":" << request->password() << "@" << request->cameraip() << ":"
           << request->cameraport() << "/h264/ch1/main/av_stream";
        std::string rtsp1 = ss.str();
        ss.str( "" );
        ss << "rtsp://" << request->username() << ":" << request->password() << "@" << request->cameraip() << ":"
           << request->cameraport() << "/h264/ch33/main/av_stream";
        std::string rtsp2 = ss.str();
        std::string rtmp = request->rtmpurl();
        ss.str( "" );
        ss << "\nargv[1]:" << rtsp1 << std::endl;
        ss << "argv[2]:" << rtsp2 << std::endl;
        ss << "argv[3]:" << rtmp << std::endl;
        Poco::Util::Application::instance().logger().information( ss.str() );

        std::string cmd( "rtmp-stream-pusher" );
        std::vector<std::string> args;
        args.push_back( rtsp1 );
        args.push_back( rtsp2 );
        args.push_back( rtmp );
        std::cout << request->xmin() << "," << request->ymin() << "," << request->xmax() << "," << request->ymax()
                  << std::endl;
       
        args.push_back( std::to_string(request->xmin() ) );
        args.push_back( std::to_string( request->ymin() ) );
        args.push_back( std::to_string( request->xmax() ) );
        args.push_back( std::to_string( request->ymax() ) );


        pid_t lastpid = getLastPid();
        if ( lastpid != -1 ) {
            if ( Process::isRunning( lastpid ) ){
				Process::requestTermination( lastpid );
			}    
        }
        Poco::Util::Application::instance().logger().information( "prepare push stream:" + rtmp );
        ProcessHandle ph = Process::launch( cmd, args, 0, 0, nullptr );
        writePid2File( ph.id() );
        int recode;
        ( Process::isRunning( ph.id() ) ) ? recode = 0 : recode = 255;
        reply->set_code( recode );
        if ( recode == 0 )
            reply->set_message( "OK" );
        else {
            reply->set_message( "ERROR" );
        }
        return Status::OK;
    }
};

void RunServer( const std::string& host ) {
    std::string server_address( host );
    FusionServiceImpl service;
    ServerBuilder builder;
    builder.AddListeningPort( server_address, grpc::InsecureServerCredentials() );
    builder.RegisterService( &service );
    std::unique_ptr<Server> server( builder.BuildAndStart() );
    std::cout << "Server listening on " << server_address << std::endl;
    server->Wait();
}

#endif